package org.hfy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.hfy.dto.ContractAuditDTO;
import org.hfy.dto.ContractQueryDTO;
import org.hfy.entity.Contract;
import org.hfy.entity.Customer;
import org.hfy.entity.Employee;
import org.hfy.entity.Quotation;
import org.hfy.enums.ContractStatus;
import org.hfy.mapper.ContractMapper;
import org.hfy.service.ContractService;
import org.hfy.service.CustomerService;
import org.hfy.service.EmployeeService;
import org.hfy.service.QuotationService;
import org.hfy.utils.ContractHtmlTemplateProcessor;
import org.hfy.utils.HtmlToPdfUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 合同服务实现类
 *
 * @author hfy
 * @version 1.0
 */
@Slf4j
@Service
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {

    private final QuotationService quotationService;
    private final CustomerService customerService;
    private final EmployeeService employeeService;

    public ContractServiceImpl(@Lazy QuotationService quotationService,
                                @Lazy CustomerService customerService,
                                @Lazy EmployeeService employeeService) {
        this.quotationService = quotationService;
        this.customerService = customerService;
        this.employeeService = employeeService;
    }

    @Override
    public IPage<Contract> getContractPage(ContractQueryDTO query) {
        Page<Contract> page = new Page<>(query.getCurrent(), query.getSize());
        return baseMapper.selectContractPage(page, query);
    }

    @Override
    public Contract getContractWithQuotationById(Long id) {
        log.info("开始获取合同详情，合同ID: {}", id);

        Contract contract = baseMapper.selectContractWithQuotationById(id);
        log.info("第一步：从数据库获取合同信息，合同: {}", contract != null ? contract.getContractNo() : "null");

        if (contract != null && contract.getQuotationId() != null) {
            log.info("第二步：合同关联报价单ID: {}", contract.getQuotationId());

            // 获取包含完整物料详情的报价单信息
            Quotation quotation = quotationService.getQuotationWithItemsById(contract.getQuotationId());
            log.info("第三步：获取报价单信息，报价单号: {}, items数量: {}",
                    quotation != null ? quotation.getQuotationNo() : "null",
                    quotation != null && quotation.getItems() != null ? quotation.getItems().size() : "null");

            contract.setQuotation(quotation);
            log.info("第四步：设置报价单信息到合同中完成");
        } else {
            log.warn("合同不存在或报价单ID为空，合同ID: {}", id);
        }

        return contract;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditContract(Long id, ContractAuditDTO auditDTO) {
        Contract contract = getById(id);
        if (contract == null) {
            throw new RuntimeException("合同不存在");
        }

        // 更新合同审核信息
        contract.setStatus(auditDTO.getStatus());
        contract.setAuditBy(auditDTO.getAuditBy());
        contract.setAuditTime(LocalDateTime.now());
        contract.setAuditRemark(auditDTO.getAuditRemark());

        boolean result = updateById(contract);
        
        // 如果合同更新成功，同步更新报价单状态
        if (result && contract.getQuotationId() != null) {
            try {
                if ("AUDIT_PASSED".equals(auditDTO.getStatus()) || "审核通过".equals(auditDTO.getStatus())) {
                    // 合同审核通过，更新报价单状态为合同审核通过
                    quotationService.updateStatusToContractApproved(contract.getQuotationId());
                    log.info("合同审核通过，已更新报价单状态为合同审核通过，报价单ID: {}", contract.getQuotationId());
                } else if ("AUDIT_REJECTED".equals(auditDTO.getStatus()) || "审核拒绝".equals(auditDTO.getStatus())) {
                    // 合同审核拒绝，更新报价单状态为合同审核拒绝
                    quotationService.updateStatusToContractRejected(contract.getQuotationId());
                    log.info("合同审核拒绝，已更新报价单状态为合同审核拒绝，报价单ID: {}", contract.getQuotationId());
                }
            } catch (Exception e) {
                log.error("更新报价单状态失败，报价单ID: {}, 错误: {}", contract.getQuotationId(), e.getMessage(), e);
                // 这里不抛出异常，避免影响合同审核的主要流程
            }
        }

        return result;
    }

    @Override
    public byte[] generateContractPdf(Long id) {
        Contract contract = getContractWithQuotationById(id);
        if (contract == null) {
            throw new RuntimeException("合同不存在");
        }

        try {
            log.info("开始生成合同HTML，合同ID: {}, 合同编号: {}", id, contract.getContractNo());

            // 查询客户和员工信息
            Customer customer = null;
            Employee employee = null;
            
            if (contract.getQuotation() != null) {
                // 根据客户代码查询客户信息
                if (contract.getQuotation().getCustomerCode() != null) {
                    QueryWrapper<Customer> customerWrapper = new QueryWrapper<>();
                    customerWrapper.eq("customer_code", contract.getQuotation().getCustomerCode());
                    customerWrapper.eq("deleted", false);
                    customer = customerService.getOne(customerWrapper);
                    log.info("查询客户信息：{}", customer != null ? customer.getCustomerName() : "未找到");
                }
                
                // 根据业务员名称查询员工信息
                if (contract.getQuotation().getSalesperson() != null) {
                    QueryWrapper<Employee> employeeWrapper = new QueryWrapper<>();
                    employeeWrapper.eq("employee_name", contract.getQuotation().getSalesperson());
                    employeeWrapper.eq("deleted", false);
                    employee = employeeService.getOne(employeeWrapper);
                    log.info("查询员工信息：{}", employee != null ? employee.getEmployeeName() : "未找到");
                }
            }

            // 使用HTML模板生成合同内容
            String htmlContent = ContractHtmlTemplateProcessor.generateContractFromTemplate(contract, customer, employee);

            // 更新合同内容到数据库
            contract.setContractContent(htmlContent);
            updateById(contract);

            // 返回HTML内容的字节数组
            return htmlContent.getBytes("UTF-8");

        } catch (Exception e) {
            log.error("生成合同HTML失败，合同ID: {}, 错误: {}", id, e.getMessage(), e);
            // 返回错误HTML
            String errorHtml = generateErrorHtml("合同生成失败: " + e.getMessage());
            try {
                return errorHtml.getBytes("UTF-8");
            } catch (Exception encodingError) {
                return "合同生成失败".getBytes();
            }
        }
    }

    @Override
    public String generateContractHtml(Long id) {
        Contract contract = getContractWithQuotationById(id);
        if (contract == null) {
            throw new RuntimeException("合同不存在");
        }

        try {
            log.info("开始生成合同HTML，合同ID: {}, 合同编号: {}", id, contract.getContractNo());

            // 查询客户和员工信息
            Customer customer = null;
            Employee employee = null;
            
            if (contract.getQuotation() != null) {
                // 根据客户代码查询客户信息
                if (contract.getQuotation().getCustomerCode() != null) {
                    QueryWrapper<Customer> customerWrapper = new QueryWrapper<>();
                    customerWrapper.eq("customer_code", contract.getQuotation().getCustomerCode());
                    customerWrapper.eq("deleted", false);
                    customer = customerService.getOne(customerWrapper);
                    log.info("查询客户信息：{}", customer != null ? customer.getCustomerName() : "未找到");
                }
                
                // 根据业务员名称查询员工信息
                if (contract.getQuotation().getSalesperson() != null) {
                    QueryWrapper<Employee> employeeWrapper = new QueryWrapper<>();
                    employeeWrapper.eq("employee_name", contract.getQuotation().getSalesperson());
                    employeeWrapper.eq("deleted", false);
                    employee = employeeService.getOne(employeeWrapper);
                    log.info("查询员工信息：{}", employee != null ? employee.getEmployeeName() : "未找到");
                }
            }

            // 使用HTML模板生成合同内容
            String htmlContent = ContractHtmlTemplateProcessor.generateContractFromTemplate(contract, customer, employee);

            // 更新合同内容到数据库
            contract.setContractContent(htmlContent);
            updateById(contract);

            return htmlContent;

        } catch (Exception e) {
            log.error("生成合同HTML失败，合同ID: {}, 错误: {}", id, e.getMessage(), e);
            // 返回错误HTML
            return generateErrorHtml("合同生成失败: " + e.getMessage());
        }
    }

    @Override
    public byte[] downloadContractPdf(Long id) {
        Contract contract = getContractWithQuotationById(id);
        if (contract == null) {
            throw new RuntimeException("合同不存在");
        }

        try {
            log.info("开始生成合同PDF下载，合同ID: {}, 合同编号: {}", id, contract.getContractNo());

            // 获取或生成HTML内容
            String htmlContent;
            if (contract.getContractContent() == null || contract.getContractContent().trim().isEmpty()) {
                // 如果数据库中没有HTML内容，先生成
                // 查询客户和员工信息
                Customer customer = null;
                Employee employee = null;
                
                if (contract.getQuotation() != null) {
                    // 根据客户代码查询客户信息
                    if (contract.getQuotation().getCustomerCode() != null) {
                        QueryWrapper<Customer> customerWrapper = new QueryWrapper<>();
                        customerWrapper.eq("customer_code", contract.getQuotation().getCustomerCode());
                        customerWrapper.eq("deleted", false);
                        customer = customerService.getOne(customerWrapper);
                    }
                    
                    // 根据业务员名称查询员工信息
                    if (contract.getQuotation().getSalesperson() != null) {
                        QueryWrapper<Employee> employeeWrapper = new QueryWrapper<>();
                        employeeWrapper.eq("employee_name", contract.getQuotation().getSalesperson());
                        employeeWrapper.eq("deleted", false);
                        employee = employeeService.getOne(employeeWrapper);
                    }
                }
                
                htmlContent = ContractHtmlTemplateProcessor.generateContractFromTemplate(contract, customer, employee);
                contract.setContractContent(htmlContent);
                updateById(contract);
                log.info("合同HTML内容已生成并保存到数据库");
            } else {
                htmlContent = contract.getContractContent();
                log.info("使用数据库中已有的合同HTML内容");
            }

            // 将HTML转换为PDF
            byte[] pdfBytes = HtmlToPdfUtils.convertHtmlToPdfSafe(htmlContent);
            log.info("合同PDF生成成功，PDF大小: {} bytes", pdfBytes.length);

            return pdfBytes;

        } catch (Exception e) {
            log.error("生成合同PDF失败，合同ID: {}, 错误: {}", id, e.getMessage(), e);
            // 返回错误PDF
            return HtmlToPdfUtils.convertHtmlToPdfSafe(generateErrorHtml("合同PDF生成失败: " + e.getMessage()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long generateContractByQuotationId(Long quotationId) {
        // 获取报价单信息（包含明细）
        Quotation quotation = quotationService.getQuotationWithItemsById(quotationId);
        if (quotation == null) {
            throw new RuntimeException("报价单不存在");
        }

        // 检查报价单状态：允许"已提交"和"已生成合同"状态
        if (!"已提交".equals(quotation.getStatus()) && !"已生成合同".equals(quotation.getStatus())) {
            throw new RuntimeException("只有已提交或已生成合同状态的报价单才能生成合同");
        }

        // 检查是否已存在合同，如果存在则删除
        Contract existingContract = baseMapper.selectByQuotationId(quotationId);
        if (existingContract != null) {
            log.info("发现已存在的合同，将删除重新生成。原合同编号: {}, 报价单ID: {}",
                    existingContract.getContractNo(), quotationId);

            // 逻辑删除旧合同
//            existingContract.setDeleted(true);
            removeById(existingContract);

            log.info("已删除原合同，合同编号: {}", existingContract.getContractNo());
        }

        // 生成合同编号
        String contractNo = generateContractNo();

        // 创建新合同
        Contract contract = new Contract();
        contract.setContractNo(contractNo);
        contract.setQuotationId(quotationId);
        contract.setStatus(ContractStatus.PENDING_AUDIT.getCode());

        // 生成合同内容HTML
        String contractContent = generateContractContent(quotation, contractNo);
        contract.setContractContent(contractContent);

        // 保存新合同
        save(contract);

        // 更新报价单状态为已生成合同，并设置合同编号
        quotation.setStatus("已生成合同");
        quotation.setContractNo(contractNo);
        quotationService.updateById(quotation);

        String operationType = existingContract != null ? "重新生成" : "生成";
        log.info("成功{}合同，合同编号: {}, 报价单ID: {}", operationType, contractNo, quotationId);

        return contract.getId();
    }

    @Override
    public String generateContractNo() {
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String prefix = "HT" + dateStr;

        // 查询当天已有的合同数量
        long count = baseMapper.countContractsByDate(LocalDate.now());
        int sequence = (int) (count + 1);

        return prefix + String.format("%04d", sequence);
    }

    /**
     * 生成合同内容HTML
     */
    private String generateContractContent(Quotation quotation, String contractNo) {
        try {
            // 暂时直接使用简单合同内容生成方法
            return generateSimpleContractContent(quotation, contractNo);
        } catch (Exception e) {
            log.error("生成合同内容失败: {}", e.getMessage(), e);
            // 如果生成失败，返回错误HTML
            return generateErrorHtml("合同内容生成失败: " + e.getMessage());
        }
    }

    /**
     * 生成简单的合同内容（备用方案）
     */
    private String generateSimpleContractContent(Quotation quotation, String contractNo) {
        StringBuilder content = new StringBuilder();
        content.append("<!DOCTYPE html>");
        content.append("<html><head><meta charset='UTF-8'><title>PCB加工合同</title></head><body>");
        content.append("<div style='text-align: center; margin-bottom: 30px;'>");
        content.append("<h1>PCB印制电路板加工合同</h1>");
        content.append("<p><strong>合同编号：").append(contractNo).append("</strong></p>");
        content.append("</div>");

        content.append("<div style='margin: 20px 0;'>");
        content.append("<p><strong>甲方（客户）：</strong>").append(quotation.getCustomerName()).append("</p>");
        content.append("<p><strong>客户代码：</strong>").append(quotation.getCustomerCode()).append("</p>");
        content.append("<p><strong>乙方（承制方）：</strong>PCB印制电路板加工厂</p>");
        content.append("<p><strong>业务员：</strong>").append(quotation.getSalesperson()).append("</p>");
        content.append("<p><strong>订单日期：</strong>").append(quotation.getOrderDate()).append("</p>");
        content.append("</div>");

        if (quotation.getItems() != null && !quotation.getItems().isEmpty()) {
            content.append("<div style='margin: 20px 0;'>");
            content.append("<h3>物料清单</h3>");
            content.append("<table border='1' style='border-collapse: collapse; width: 100%;'>");
            content.append("<tr style='background-color: #f5f5f5;'>");
            content.append("<th>序号</th><th>产品名称</th><th>数量</th><th>单价</th><th>其他费用</th><th>金额</th><th>备注</th>");
            content.append("</tr>");

            quotation.getItems().forEach(item -> {
                content.append("<tr>");
                content.append("<td style='text-align: center;'>").append(item.getItemNo()).append("</td>");
                content.append("<td>").append(item.getProductName()).append("</td>");
                content.append("<td style='text-align: center;'>").append(item.getQuantity()).append("</td>");
                content.append("<td style='text-align: right;'>")
                       .append(item.getUnitPrice() != null ? item.getUnitPrice() : "0.00").append("</td>");
                content.append("<td style='text-align: right;'>")
                       .append(item.getOtherFee() != null ? item.getOtherFee() : "0.00").append("</td>");
                content.append("<td style='text-align: right;'>")
                       .append(item.getTotalAmount() != null ? item.getTotalAmount() : "0.00").append("</td>");
                content.append("<td>")
                       .append(item.getItemRemark() != null ? item.getItemRemark() : "").append("</td>");
                content.append("</tr>");
            });
            content.append("</table>");
            content.append("</div>");
        }

        content.append("<div style='margin: 20px 0;'>");
        content.append("<p><strong>付款方式：</strong>").append(quotation.getPaymentMethod()).append("</p>");
        content.append("<p><strong>是否含税：</strong>")
               .append(Boolean.TRUE.equals(quotation.getIsTaxIncluded()) ? "是（增值税票13%）" : "否")
               .append("</p>");
        content.append("<p><strong>合同总金额：</strong>")
               .append(quotation.getTotalAmount() != null ? quotation.getTotalAmount() : "0.00")
               .append(" 元</p>");
        content.append("</div>");

        content.append("</body></html>");

        return content.toString();
    }

    /**
     * 生成错误页面HTML
     */
    private String generateErrorHtml(String errorMessage) {
        return "<!DOCTYPE html>" +
               "<html><head><meta charset='UTF-8'><title>PDF生成错误</title></head><body>" +
               "<div style='text-align: center; margin: 50px;'>" +
               "<h2>PDF生成错误</h2>" +
               "<p>" + errorMessage + "</p>" +
               "</div>" +
               "</body></html>";
    }
}
